import { h } from 'vue';
import { get, uniqueId } from 'lodash-es';
import { viewImages } from '../img-viewer/viewer.js';
import Modal from 'ant-design-vue/es/modal/index.js';

export const acceptTypes = {
  image: {
    title: '图片',
    mime: 'image/gif,image/png,image/jpeg,image/bmp,image/webp',
    suffix: 'gif,png,jpg,jpeg,bmp,webp',
  },
  video: {
    title: '视频',
    mime: 'video/mp4,video/mpeg,video/webm,video/ogg,video/x-flv,video/x-msvideo,video/quicktime,video/x-ms-wmv,video/x-matroska',
    suffix: 'mp4,mpg,mpe,mpeg,webm,ogg,flv,avi,mov,wmv,mkv',
  },
  audio: {
    title: '音频',
    mime: 'audio/midi,audio/mpeg,audio/webm,audio/ogg,audio/wav,audio/x-m4a,audio/x-mpegurl,audio/aac,audio/flac',
    suffix: 'midi,mp3,ogg,wav,m3u,m4a,aac,flac',
  },
  doc: {
    title: '文档',
    mime: 'text/plain,text/csv,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel.sheet.macroenabled.12,application/vnd.ms-excel.sheet.binary.macroenabled.12,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.ms-powerpoint.presentation.macroenabled.12',
    suffix: 'txt,csv,pdf,doc,dot,docx,dotx,xls,xlt,xla,xlsx,xlsm,xlsb,ppt,pptx,pptm',
  },
};

export function getFileType(file) {
  if (!file || typeof file !== 'object') {
    return;
  }
  const includes = (types, type) => {
    return types.split(',').includes(type);
  };
  for (const key in acceptTypes) {
    const { mime, suffix } = acceptTypes[key];
    if (includes(mime, file.type) || includes(suffix, getSuffix(file.name))) {
      return key;
    }
  }
}

export function getFileUrl(file) {
  let url = URL.createObjectURL(file);
  setTimeout(() => {
    URL.revokeObjectURL(url);
    url = null;
  }, 50);
  return url;
}

export function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onerror = (error) => reject(error);
    reader.onload = () => resolve(reader.result);
    reader.readAsDataURL(file);
  });
}

export function getSuffix(str) {
  if (typeof str === 'string' && str.indexOf('.') > 0) {
    return str.split('.').pop().toLocaleLowerCase();
  }
  return '';
}

export function getUrlName(str) {
  return typeof str === 'string' ? str.split('/').pop() : '';
}

export function getAcceptTypes(accepts, options = {}) {
  const getter = (accept, options) => {
    const { useDefault, enableNone } = options;
    let val = acceptTypes[accept];
    if (!val) {
      val = useDefault !== false ? acceptTypes.image : enableNone === true ? null : {};
    }
    return val;
  };
  if (typeof accepts === 'string' && accepts.indexOf(',') >= 0) {
    accepts = accepts.split(',');
  }
  if (Array.isArray(accepts)) {
    let { useDefault, enableNone } = options;
    let res = { mime: '', suffix: '' };
    res = accepts.reduce((res, item) => {
      const opt = getter(item, options);
      if (!opt) {
        return res;
      }
      return {
        mime: [res.mime, get(opt, 'mime')].join(','),
        suffix: [res.suffix, get(opt, 'suffix')].join(','),
      };
    }, res);
    res.mime.replace(/^,/, '');
    res.suffix.replace(/^,/, '');
    if (!res.mime || !res.suffix) {
      res = useDefault !== false ? acceptTypes.image : enableNone === true ? null : {};
    }
    return res;
  }
  return getter(accepts, options);
}

export function getWrappedFile(file, extraData) {
  /*
   * 主要用于将 input 接收到的 file 对象文件进行包装
   * */
  if (!(file instanceof File)) {
    throw new Error('file is not a File object');
  }
  const opt = {
    uid: uniqueId(),
    url: getFileUrl(file),
    name: file.name,
    type: file.type,
    suffix: getSuffix(file),
    originFileObj: file,
    status: 'waiting',
  };
  return Object.assign(opt, extraData);
}

export function getFileList(values, names) {
  /*
   * 主要用于处理接口返回的文件地址用于回显
   * 'values: 'url,url,...' or ['url','url',...]
   * 'names: 'name,name,...' or ['name','name',...]
   * */
  const format = (values) => {
    if (!values) {
      return [];
    }
    if (typeof values === 'string') {
      values = values.split(',');
    }
    return Array.isArray(values) ? values : [];
  };
  values = format(values);
  names = format(names);
  return values.reduce((res, item, index) => {
    if (!item || typeof item !== 'string') {
      return res;
    }
    const filename = names[index] || getUrlName(item);
    res.push({
      uid: uniqueId(),
      url: item,
      name: filename,
      type: getSuffix(item),
      suffix: getSuffix(item),
      response: { data: { url: item, filename } },
      status: 'done',
    });
    return res;
  }, []);
}

export function isImage(file) {
  return getFileType(file) === 'image';
}

export function isVideo(file) {
  return getFileType(file) === 'video';
}

export function isAudio(file) {
  return getFileType(file) === 'audio';
}

export function isDoc(file) {
  return getFileType(file) === 'doc';
}

export function isFileExist(file, fileList) {
  return fileList.some((item) => item.name === file.name);
}

export function isFileAcceptable(file, accept) {
  if (accept === undefined || accept === null || accept === '') {
    return true;
  }
  const opt = getAcceptTypes(accept, {
    useDefault: false,
    enableNone: true,
  });
  if (!file || !(file instanceof File) || !opt) {
    return false;
  }
  const isMatch = (str, val) => {
    return str.split(',').includes(val);
  };
  return isMatch(opt.mime, file.type) || isMatch(opt.suffix, getSuffix(file.name));
}

export async function handlePreview(file) {
  let url = null;
  if (file instanceof File) {
    url = await getBase64(file);
  } else if (file && typeof file === 'object') {
    if (file.url) {
      url = file.url;
    } else if (file.originFileObj instanceof File) {
      url = await getBase64(file.originFileObj);
    }
  }
  if (url) {
    viewImages(url);
  }
}

export function handleNotice(accepts) {
  let list = [];
  if (Array.isArray(accepts)) {
    list = accepts;
  } else if (typeof accepts === 'string' && accepts.indexOf(',') >= 0) {
    list = accepts.split(',');
  }
  list = list.reduce((res, item) => {
    const opt = getAcceptTypes(item, { useDefault: false, enableNone: true });
    if (opt) {
      res.push(opt);
    }
    return res;
  }, []);
  Modal.info({
    title: h('div', { style: 'color: red' }, '文件格式不符合要求！'),
    content: h('div', {}, [
      h('div', { style: 'margin: 0 0 16px' }, '仅支持如下格式：'),
      list.map(({ title, suffix }) => {
        suffix = suffix.replace(/,/g, '，');
        return h('div', { style: 'display: flex;' }, [
          h('div', { style: 'flex: none' }, title + '：'),
          h('div', { style: 'white-space: pre-wrap;word-break: break-all;letter-spacing: 0' }, suffix),
        ]);
      }),
    ]),
  });
}
